package org.jeecg.report.utils;



import org.jeecg.qis.entity.QisSpcdetailCfg;
import org.jeecg.report.dto.QisSpcChartDataDTO;
import org.jeecg.report.entity.QisSpcPointValue;
import org.jeecg.report.enums.SpcD2Enum;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;

import static java.util.stream.Collectors.toList;

public class QisSpcUtil {
    /**
     * 计算单值图控制线
     *
     * @param qisSpcChartDataDTO
     */
    public static void singleValueControlLimit(QisSpcChartDataDTO qisSpcChartDataDTO, List<QisSpcPointValue> list, List<QisSpcPointValue> rangeList) {
        //计算均值线
        BigDecimal clX = avg(list);
        //计算极差线
        BigDecimal clR = avg(rangeList);
        //计算单值上线
        BigDecimal uclX = clX.add(clR.multiply(BigDecimal.valueOf(2.660))).setScale(6, RoundingMode.DOWN);
        ;
        //计算单值下线
        BigDecimal lclX = clX.subtract(clR.multiply(BigDecimal.valueOf(2.660))).setScale(6, RoundingMode.DOWN);
        ;
        //计算极差上线
        BigDecimal uclR = clR.multiply(BigDecimal.valueOf(3.267)).setScale(6, RoundingMode.DOWN);
        ;
        qisSpcChartDataDTO.setClX(clX);
        qisSpcChartDataDTO.setClR(clR);
        qisSpcChartDataDTO.setUclX(uclX);
        qisSpcChartDataDTO.setLclX(lclX);
        qisSpcChartDataDTO.setUclR(uclR);
        qisSpcChartDataDTO.setLclR(new BigDecimal("0.0"));
    }

    /**
     * 计算均值图控制线
     *
     * @param qisSpcChartDataDTO
     */
    public static void meanValueControlLimit(QisSpcChartDataDTO qisSpcChartDataDTO, List<QisSpcPointValue> list, List<QisSpcPointValue> rangeList) {
        //计算均值线
        BigDecimal clX = avg(list);
        //计算极差均值线
        BigDecimal clR = avg(rangeList);
        //计算上线
        BigDecimal uclX = clX.add(clR.multiply(BigDecimal.valueOf(1.023))).setScale(6, RoundingMode.DOWN);
        ;
        //计算下线
        BigDecimal lclX = clX.subtract(clR.multiply(BigDecimal.valueOf(1.023))).setScale(6, RoundingMode.DOWN);
        ;
        //计算极差上线
        BigDecimal uclR = clR.multiply(BigDecimal.valueOf(2.574)).setScale(6, RoundingMode.DOWN);
        ;
        qisSpcChartDataDTO.setClX(clX);
        qisSpcChartDataDTO.setClR(clR);
        qisSpcChartDataDTO.setUclX(uclX);
        qisSpcChartDataDTO.setLclX(lclX);
        qisSpcChartDataDTO.setUclR(uclR);
        qisSpcChartDataDTO.setLclR(new BigDecimal("0.0"));
    }

    /**
     * 求均值
     *
     * @param list
     * @return
     */
    public static BigDecimal avg(List<QisSpcPointValue> list) {
        BigDecimal sum = list.stream().map(QisSpcPointValue::getValue)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return sum.divide(BigDecimal.valueOf(list.size()), 6, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 求最大值
     *
     * @param list
     * @return
     */
    public static BigDecimal getMax(List<QisSpcPointValue> list) {
        return list.stream().max(Comparator.comparing(QisSpcPointValue::getValue)).get().getValue();
    }

    /**
     * 求最小值
     *
     * @param list
     * @return
     */
    public static BigDecimal getMin(List<QisSpcPointValue> list) {
        return list.stream().min(Comparator.comparing(QisSpcPointValue::getValue)).get().getValue();
    }

    /**
     * 求中位数
     *
     * @param list
     * @return
     */
    public static BigDecimal getMedian(List<QisSpcPointValue> list) {
        List<BigDecimal> values = list.stream().map(QisSpcPointValue::getValue).sorted().collect(toList());
        BigDecimal j;
        if (list.size() % 2 == 0) {
            j = values.get(values.size() / 2 - 1).add(values.get(values.size() / 2)).divide(BigDecimal.valueOf(2), 6, RoundingMode.HALF_UP);
        } else {
            j = values.get(values.size() / 2);
        }
        return j;
    }

    /**
     * 求西格玛（总）
     *
     * @param list
     * @param avg
     * @param count
     * @return
     */
    public static BigDecimal getSigmaP(List<QisSpcPointValue> list, BigDecimal avg, Integer count) {
        BigDecimal sum = BigDecimal.valueOf(0.0);
        for (QisSpcPointValue item : list) {
            sum = sum.add(item.getValue().subtract(avg).pow(2));
        }
        BigDecimal value = BigDecimal.valueOf(count - 1);
        BigDecimal divide = sum.divide(value, 10, RoundingMode.HALF_UP);
        return BigDecimal.valueOf(Math.sqrt(divide.doubleValue()));
    }

    /**
     * 求西格玛（组内）
     *
     * @param RI
     * @param n
     * @return
     */
    public static BigDecimal getSigma(BigDecimal RI, Integer n) {
        Double constant = SpcD2Enum.getConstant(n);
        return RI.divide(BigDecimal.valueOf(constant), 6, RoundingMode.HALF_UP);
    }

    /**
     * 求CPU或PPU
     *
     * @param usl
     * @param avg
     * @param sigma
     * @return
     */
    public static BigDecimal getCpuORPpu(BigDecimal usl, BigDecimal avg, BigDecimal sigma) {
        return usl.subtract(avg).divide(sigma.multiply(BigDecimal.valueOf(3)), 6, RoundingMode.HALF_UP);
    }

    /**
     * 求CPL或PPL
     *
     * @param lsl
     * @param avg
     * @param sigma
     * @return
     */
    public static BigDecimal getCplORPpl(BigDecimal lsl, BigDecimal avg, BigDecimal sigma) {
        return avg.subtract(lsl).divide(sigma.multiply(BigDecimal.valueOf(3)), 6, RoundingMode.HALF_UP);
    }

    /**
     * 求CP或PP
     *
     * @param usl
     * @param lsl
     * @param sigma
     * @return
     */
    public static BigDecimal getCpORPp(BigDecimal usl, BigDecimal lsl, BigDecimal sigma) {
        return usl.subtract(lsl).divide(sigma.multiply(BigDecimal.valueOf(6)), 6, RoundingMode.HALF_UP);
    }

    /**
     * 计算八大判异
     */
    public static List<QisSpcPointValue> getAbnormal(List<QisSpcPointValue> list, List<QisSpcdetailCfg> detailList) {

        //循环列表
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < detailList.size(); j++) {

            }
        }
        return null;
    }

    public static List<QisSpcPointValue> getAbnormal1(List<QisSpcPointValue> list, QisSpcdetailCfg detailList,QisSpcChartDataDTO qisSpcChartDataDTO) {
        //获取标准差
        BigDecimal sigma = qisSpcChartDataDTO.getSigma();
        Integer k = detailList.getKvalue();
        //循环列表
        for (int i = 0; i < list.size(); i++) {

        }
        return null;
    }

}
